package org.gwtEss.table;

import org.gwtEss.client.GwtEss;
import org.gwtEss.link.LabelLink;
import org.gwtEss.other.Div;
import org.gwtEss.other.DragTrack;

import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.MouseDownEvent;
import com.google.gwt.event.dom.client.MouseDownHandler;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.PopupPanel;
import com.google.gwt.user.client.ui.Widget;

public abstract class _HeaderTable<VO> extends Composite{
	private Cols<VO> cols;
	private int pxWidth;
	private FlexTable flexTable = new FlexTable();
	private final static int SEPERATOR_WIDTH = 2, SORT_WIDTH = 7, MIN_WIDTH = 16, LAST_COL_WIDTH = 17, DETAIL_TABLE_WIDTH = 170;
	private final static int GRID_COL_NAME = 0, GRID_COL_SORT = 1, GRID_COL_SEPERATOR = 2; 
//	private ArrayList<ColWidget> visibleCols = new ArrayList<ColWidget>();
	
	private Cols<VO> visibleCols = new Cols<VO>();
	
	private PopupPanel headerDetailsPopup;
	private HeaderDetailWidget<VO> headerDetailWidget;
//	private ColWidget resizeCol = null; 
	private int startX = -1; 
	private DragTrack dt = null;
	public abstract void onResizeBegin(ColWidget leftCol, ColWidget rightCol);
	public abstract void onResizeEnd(ColWidget leftCol, ColWidget rightCol);
	public abstract void onColVisibilityChanged(Cols<VO> visibleCols);
	
	public _HeaderTable(Cols<VO> cols, int pxWidth) {
		this.cols = cols; 
		this.pxWidth = pxWidth;
		initWidget(flexTable);
		flexTable.getRowFormatter().addStyleName(0, "table-header");
		flexTable.setCellPadding(0);
		flexTable.setCellSpacing(0);
		flexTable.setHeight("25px");

		renderVisibleCols();
		
	}

	private void updateVisibleCols(){
		visibleCols.clear();
		for (ColWidget col: cols)
			if (col.isVisible())
			visibleCols.add(col);
	}
	private void renderVisibleCols(){
		updateVisibleCols();
		flexTable.clear();
		int actualAvailableWidth = pxWidth - LAST_COL_WIDTH; 
		int widthSoFar = 0, colW;
		
		for (int i=0; i<visibleCols.size(); i++){
			ColWidget colWidget = visibleCols.get(i);
			int suggestedColWidth = colWidget.getSuggestedWidth();
			if (i != visibleCols.size()-1 && suggestedColWidth > MIN_WIDTH && (actualAvailableWidth - (widthSoFar + suggestedColWidth) > ((visibleCols.size() - i)*MIN_WIDTH))){
				colW = suggestedColWidth;
			}else{
				colW = (int)Math.floor (((double)(actualAvailableWidth - widthSoFar))/((double)(visibleCols.size() - i)));
			}
			colWidget.setColWidth(colW);
			flexTable.setWidget(0, i, getCellWidget(colWidget));
			widthSoFar += colWidget.getColWidth();
		}
		flexTable.setWidget(0, visibleCols.size(), getLastCol());
		flexTable.getCellFormatter().setHorizontalAlignment(0, visibleCols.size(), HasHorizontalAlignment.ALIGN_CENTER);
	}
	private LabelLink getLastCol(){
		LabelLink lastColumn = new LabelLink("...");
		lastColumn.addClickHandler(new ClickHandler(){

			public void onClick(ClickEvent event) {
				showHeaderDetailsPopup(event.getNativeEvent().getClientX(), event.getNativeEvent().getClientY());
			}
			
		});
		lastColumn.setWidth(LAST_COL_WIDTH + "px");
		return lastColumn;
	}


	private void showHeaderDetailsPopup(int left, int top){
		if (headerDetailsPopup == null){
			headerDetailWidget = new HeaderDetailWidget<VO>(cols){

				@Override
				boolean resetColVisibility(ColWidget col) {
//					showHideCol(col);
					renderVisibleCols();
					onColVisibilityChanged(visibleCols);
					return true;
				}

			};
			headerDetailWidget.setWidth(DETAIL_TABLE_WIDTH + "px");
			headerDetailsPopup = new PopupPanel(true);
			headerDetailsPopup.setAnimationEnabled(true);
			headerDetailsPopup.setWidget(headerDetailWidget);
			headerDetailWidget.render();			
		}
		int leftX = left-DETAIL_TABLE_WIDTH;
		headerDetailsPopup.setPopupPosition(leftX < 0? 0: leftX, top);
		headerDetailsPopup.show();
	}

/*	
	private void changeText(Grid g, int width, String txt){
		g.setText(0, 0, Helper.getTxtBasedOnPx(txt, width));
	}
	*/
	
	
	private void changeText(final Grid g, int width, ColWidget col){
		Widget w = null;
		try {
			w = g.getWidget(0, GRID_COL_NAME);	
		}catch (Exception ex){}
		if (w == null){
			w = new HTML(col.getColName());
			w.setTitle(col.getColName());
			w.addStyleName("divClip");
			g.setWidget(0, GRID_COL_NAME, w);
			((HTML)w).addClickHandler(new ClickHandler(){

				public void onClick(ClickEvent event) {
					setSortAsc(g, true);
				}
				
			});
		}
		w.setWidth((width - SEPERATOR_WIDTH - SORT_WIDTH) + "px");
	}
	private void setSortAsc(Grid grid, Boolean sortAsc){
		String img= sortAsc==null?"images/blank.gif":sortAsc?"images/sort_arrow_up.gif":"images/sort_arrow_down.gif";
		((Image)grid.getWidget(0, GRID_COL_SORT)).setUrl(img);
	}
	private void hideSort(Grid grid){
		setSortAsc(grid, null);
	}
	private Widget getCellWidget(final ColWidget col) {
		final Grid grid = new Grid(1, GRID_COL_SEPERATOR+1);
		grid.setCellPadding(0);
		grid.setCellSpacing(0);
//		int availableColWidth = col.getColWidth() - SEPERATOR_WIDTH;
//		grid.getCellFormatter().setWidth(0, 0, availableColWidth + "px");
//		grid.getCellFormatter().setWidth(0, 1, SORT_WIDTH + "px");
//		grid.getCellFormatter().setWidth(0, 2, SEPERATOR_WIDTH + "px");
		
		changeText(grid, col.getColWidth(), col);
		
		grid.getCellFormatter().addStyleName(0, GRID_COL_SEPERATOR, "seperator-drag");
//		Image seperator = new Image("images/header-col-split.png");
		Label seperator = new Label(){
			{
				setSize("2px", "100%");
				addStyleName("red");
			}
		};
//		grid.getCellFormatter().setWidth(0, GRID_COL_SEPERATOR, SORT_WIDTH + "px");
		Image sort = new Image();
		sort.setWidth(SORT_WIDTH + "px");
//		seperator.setWidth(SEPERATOR_WIDTH+"px");
		grid.setWidget(0, GRID_COL_SORT, sort);
		hideSort(grid);
		grid.setWidget(0, GRID_COL_SEPERATOR, seperator);
		seperator.addMouseDownHandler(new MouseDownHandler(){

			public void onMouseDown(MouseDownEvent event) {
				event.preventDefault();
//				resizeCol = col;
				startX = event.getClientX();
				dt = new DragTrack(){
					boolean firstResizeDone = false; 
					@Override
					public void onMouseMove(int mouseX) {
//						int delta =  mouseX - startX;

						doAdjustWidths(mouseX/*, false*/);
//						GwtEss.log.custom("header: " + col.getColName(), "- mouse move delta = " + delta);
					}
					
					private void doAdjustWidths(int mouseX/*, boolean isMouseUp*/){
						int delta =  mouseX - startX;
						int rightColNum = visibleCols.indexOf(col) + 1;
						ColWidget rightCol = visibleCols.get(rightColNum);
						if (!firstResizeDone && delta != 0){
							firstResizeDone = true;
							onResizeBegin(col, rightCol);
						}
						if (delta == 0){
							return;
						}
						Grid rightGrid = (Grid) flexTable.getWidget(0, rightColNum);
						int colWidth = col.getColWidth() + delta;
						int rightColWidth =rightCol.getColWidth() - delta; 
						
						if (colWidth <= MIN_WIDTH || rightColWidth <= MIN_WIDTH)
							return;
						
						grid.setWidth(colWidth + "px");
						rightGrid.setWidth(rightColWidth + "px");

						rightCol.setColWidth(rightColWidth);
						col.setColWidth(col.getColWidth() + delta);

						changeText(grid, colWidth, col);
						changeText(rightGrid, rightColWidth, rightCol);
						startX = mouseX;
					/*	if (isMouseUp){
							rightCol.setColWidth(rightColWidth);
							col.setColWidth(col.getColWidth() + delta);
						}*/
					}
					@Override
					public void onMouseUp(int mouseX) {
						doAdjustWidths(mouseX/*, true*/);
//						resizeCol = null;
						dt = null;
						
						if (firstResizeDone){
							int rightColNum = visibleCols.indexOf(col) + 1;
							ColWidget rightCol = visibleCols.get(rightColNum);
							onResizeEnd(col, rightCol);
						}
					}};
			}
			
		});
	
		return grid;
	}


}
